package com.zhang.config;

import com.zhang.security.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    LoginFailureHandler loginFailureHandler;
    @Autowired
    LoginSuccessHandler loginSuccessHandler;
    @Autowired
    CaptchaFilter captchaFilter;
    @Autowired
    JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
    @Autowired
    JwtAccessDeniedHandler jwtAccessDeniedHandler;
    @Autowired
    UserDetailServiceImpl userDetailServiceImpl;
    @Autowired
    LogoutSuccessHandler_ logoutSuccessHandler;
    @Bean
    JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception {
        JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter(authenticationManager());
        return jwtAuthenticationFilter;
    }
    @Bean
    BCryptPasswordEncoder bCryptPasswordEncoder(){  //springsecurity内置的密码加密方式
        return new BCryptPasswordEncoder();
    }
    @Autowired
    GuestFilter guestFilter;

    private static final String[] url_whiteList = {     //白名单
            "/login","/logout","/captcha","/favicon.ico","/sys/user/getAvatar/*","/down"
    };

    protected void configure(HttpSecurity http) throws Exception{
        http.cors().and().csrf().disable()
        //配置拦截规则
        .authorizeRequests()
        .antMatchers(url_whiteList).permitAll()     //白名单不拦截
        .anyRequest().authenticated()   //其他所有资源都要登录才能访问

         //登录配置
        .and()
        .formLogin()
        .successHandler(loginSuccessHandler)
        .failureHandler(loginFailureHandler)

         //退出登录配置
        .and()
        .logout()
        .logoutSuccessHandler(logoutSuccessHandler)

         //禁用session
        .and()
        .sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)

         //异常处理器
        .and()
        .exceptionHandling()
        .authenticationEntryPoint(jwtAuthenticationEntryPoint)  //用来解决匿名用户访问无权限资源时的异常
        .accessDeniedHandler(jwtAccessDeniedHandler)     //用来解决认证过的用户访问无权限资源时的异常


         //配置自定义的过滤器
        .and()
        .addFilter(jwtAuthenticationFilter())   //添加jwt认证过滤器
        .addFilterBefore(captchaFilter, UsernamePasswordAuthenticationFilter.class)//配置验证码过滤器在用户名认证过滤器之前
        .addFilterAfter(guestFilter,BasicAuthenticationFilter.class)    //游客用户限制一些权限
        ;
    }

    //UserDetailServiceImpl注入到security中，这样每次登陆的时候都会执行此用户认证服务
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailServiceImpl);
    }
}
